with Websites_Configuration; use Websites_Configuration;
with Ada.Strings.Bounded;


generic

   --
   -- maximum website size held in memory
   --

   Content_Size_Max : in Positive := STACK_LIMIT;

   --
   -- maximum length of URL including any domain, path, query string
   --

   URL_Length_Max   : in Positive := DOMAIN_MAXIMUM_LENGTH +

                                     QUERYSTRING_MAXIMUM_LENGTH;


   --
   -- Website properties, contents
   --


package Websites is

   --
   -- encapsulated type
   --

   --
   -- generic packages for type's bounded strings
   --

   package Contents_Type_Pkg is new Ada.Strings
         .Bounded
         .Generic_Bounded_Length( Max => Content_Size_Max );

   package URL_Type_Pkg is new Ada.Strings
         .Bounded
         .Generic_Bounded_Length( Max => URL_Length_Max );


   --
   -- bound string sub types as basis for the Website record
   --

   subtype Contents_Type is Contents_Type_Pkg.Bounded_String;

   subtype URL_Type is URL_Type_Pkg.Bounded_String;


   --
   -- create subtypes of String, Integer for the Website record
   --
   --    predicates ensure generics' values are never exceeded
   --
   --    suitable for use as parameter types
   --

   subtype Contents_Str_Sub_Type is String

      with Dynamic_Predicate => Contents_Str_Sub_Type'Size <= Content_Size_Max;

   subtype Contents_Int_Sub_Type is Positive

      with Dynamic_Predicate => Contents_Int_Sub_Type in 1 .. Content_Size_Max;

   subtype URL_Str is String

      with Dynamic_Predicate => URL_Str'Size <= URL_Length_Max;


   --
   -- tagged
   --
   --    implementing packages should be allowed to extend this type
   --
   -- not abstract
   --
   --    type and methods are already defined, should not require implementing
   --    class to redefine
   --
   -- not private
   --
   --    private within implementing package, cannot be private here and
   --    facilitate encapsulated methods within implementation
   --

   type Website is tagged record

      URL      : URL_Type;

      Contents : Contents_Type;

   end record;


   --
   -- pointer to the Website type to aid any derived types, providing access
   --    to parent type
   --

   type Website_Access_Type is access all Website'Class;


   --
   -- interface
   --
   --    attach methods to a Website object instance, as opposed to calling
   --       methods statically
   --

   type Website_Object_Interface_Type is interface;


   --
   -- encapsulation methods
   --


   --
   -- contents
   --

   function Get_Contents( Website_Instance : in Website_Object_Interface_Type )

         return Contents_Str_Sub_Type

         is abstract;

   procedure Set_Contents( Website_Instance : in out

                             Website_Object_Interface_Type;

                           Website_Contents : in Contents_Str_Sub_Type;

                           Append : Boolean := false )

         is abstract;

   function Size( Website_Instance : in Website_Object_Interface_Type )

         return Contents_Int_Sub_Type

         is abstract;

   procedure Erase( Website_Instance : in out Website_Object_Interface_Type )

         is abstract;


   --
   -- URL
   --

   procedure Set_URL( Website_Instance : in out Website_Object_Interface_Type;

                      URL : in URL_Str )
         is abstract;

   function Get_URL( Website_Instance : in Website_Object_Interface_Type )

         return URL_Str

         is abstract;

   --
   -- percentage bound string space used by website contents
   --

   function Percentage_Space_Used( Website_Instance : in

         Website_Object_Interface_Type )

         return Integer

         is abstract;


private


end Websites;